/**
 * @author Rid King
 * @since 2017-05-21
 * @version 2.0.0
 * @description 视图类，处理元素渲染、事件绑定
 */

import Model from '../../../../../../components/script/model/2.0.0/js/model.js'
import Domer from '../../../../../../components/script/domer/2.0.0/js/domer.js'
import Loader from '../../../../../../components/script/loader/2.0.0/js/loader.js'
import debuger from '../../../../../../components/script/debuger/2.0.0/js/debuger.js'
import objecter from '../../../../../../components/script/objecter/2.0.0/js/objecter.js'
import VirtualElement from '../../../virtual-element/2.0.0/js/virtual-element.js'
import Space from './space.js'
import ViewerNode from './viewer-node.js'
import directives from './directives/directives.js'

// 文档对象
const doc = document

class Viewer extends Model {
  /**
   * @description 构造方法
   * @param params <Object> // 配置参数
  */
  constructor (params) {
    super(params)

    // 指令组
    this._directives = []
    // 初始化控制域
    this._$initScope()
    // 参数配置
    this._$extend(params)
    // 初始化视图
    this._$initView()

    // 模板存在优先使用模板
    if (this.$scope._template) {
        this._$process()
    }
    // 加载远程模板
    else if (this.$scope._templateUrl) {
        Loader.text(this.$scope._templateUrl)
        .then((template) => {
            this.$scope._template = template
            this._$process()
        })
    }
    // 指定模板元素
    else if (this.$scope._el) {
        let el = this.$scope._el
        // 元素处理
        el = typeof el === 'string' ? Domer.querySelector(el) : el
        // 判断元素是否存在
        if (el instanceof HTMLElement) {
            this.el = el
            this.$scope._template = el.outerHTML
            this._$process()
        }
    }

    // 添加依赖
    // this.depends(dependencies)
  }

  /**
   * @description 初始化控制域
  */
  _$initScope () {
      let $scope = {}
      /****属性映射****/
      let _props = this._$scope._props
      let $props = {} // 私有属性
      for (let key in _props) {
          $props[key] = _props[key]
      }
      $scope._props = $props

      /****状态映射****/
      let _state = this._$scope._state
      let $state = {} // 私有状态
      for (let key in _state) {
          $state[key] = _state[key]
      }
      $scope._state = $state

      /****方法映射****/
      let _methods = this._$scope._methods
      let $methods = {} // 私有方法
      for (let key in _methods) {
          $methods[key] = _methods[key]
      }
      $scope._methods = $methods

      /****事件映射****/
      let _events = this._$scope._events // 原型事件
      let $events = {} // 私有事件
      for (let key in _events) {
          $events[key] = _events[key]
      }
      $scope._events = $methods

      this.$scope = $scope
  }

  /**
   * @description 初始化视图
  */
  _$initView () {
      /****属性映射****/
      let _props = this.$scope._props
      for (let key in _props) {
          this[key] = _props[key]
      }

      /****状态映射****/
      let _state = this.$scope._state
      for (let key in _state) {
          this[key] = _state[key]
      }

      /****方法映射****/
      let _methods = this.$scope._methods
      for (let key in _methods) {
          this[key] = _methods[key]
      }

      /****事件映射****/
      let _events = this.$scope._events // 原型事件
      let _$events = this._$events // 私有事件
      for (let key in _events) {
          _$events[key] = _events[key]
      }
  }

  /**
   * @description 视图处理
  */
  _$process () {
      // 编译
      this.$compile(this.$scope._template)

      // 视图挂载
      this.$mount()
  }

  /**
   * @description 申明新的视图
   * @param name <String> 视图名称
   * @param scope <Function/Object> 视图构造函数或对象
  */
  static extend (name, scope) {
      let ParentViewer = this

      // 生成属性集合
      let property = Viewer.packProto(scope)
      // 根原型
      let rootProto = Viewer.prototype
      // 父原型
      let parentProto = ParentViewer.prototype

      // 定义新视图
      class DeclareViewer extends ParentViewer {}
      // 视图原型
      let prototype = DeclareViewer.prototype

      /****模板****/
      let _template = property.template || parentProto._$scope._template || rootProto._$scope._template
      let _templateUrl = property.templateUrl || parentProto._$scope._templateUrl || rootProto._$scope._templateUrl

      /****属性****/
      let _props = {}
      // 继承
      let props = parentProto._$scope._props
      for (let key in props) {
          _props[key] = props[key]
      }

      // 自定义
      props = property.props
      for (let key in props) {
          // 根含有相同键
          if (rootProto.hasOwnProperty(key)) {
              debuger.warn(`Can not declare prop: ${key} for this Viewer,RootViewer already has this prop`)
          }
          // 父级有相同键
          else if (parentProto._$scope._state.hasOwnProperty(key) || 
                    parentProto._$scope._methods.hasOwnProperty(key)) {
              debuger.warn(`Can not declare prop: ${key} for this Viewer,ParentViewer already has this prop`)
          }
          else {
              _props[key] = props[key]
          }
      }

      /****状态****/
      let _state = {}
      // 继承
      let state = parentProto._$scope._state
      for (let key in state) {
          _state[key] = state[key]
      }

      // 自定义
      state = property.state
      for (let key in state) {
          // 根含有相应属性
          if (rootProto.hasOwnProperty(key)) {
              debuger.warn(`Can not declare prop: ${key} for this Viewer,RootViewer already has this prop`)
          }
          // 父级有相同键
          else if (parentProto._$scope._props.hasOwnProperty(key) || 
                    parentProto._$scope._methods.hasOwnProperty(key)) {
              debuger.warn(`Can not declare prop: ${key} for this Viewer,ParentViewer already has this prop`)
          }
          // 子级有相同键
          else if (prototype._$scope._props.hasOwnProperty(key)) {
              debuger.warn(`Can not declare prop: ${key} for this Viewer,Viewer already has this prop`)
          }
          else {
              _state[key] = state[key]
          }
      }

      /****方法****/
      let _methods = {}
      // 继承
      let methods = parentProto._$scope._methods
      for (let key in methods) {
          _methods[key] = methods[key]
      }

      // 自定义
      methods = property.methods
      for (let key in methods) {
          // 根含有相同键
          if (rootProto.hasOwnProperty(key)) {
              debuger.warn(`Can not declare prop: ${key} for this Viewer,RootViewer already has this prop`)
          }
          // 父级有相同键
          else if (parentProto._$scope._props.hasOwnProperty(key) || 
                    parentProto._$scope._state.hasOwnProperty(key)) {
              debuger.warn(`Can not declare prop: ${key} for this Viewer,ParentViewer already has this prop`)
          }
          // 属性有相同键
          else if (prototype._$scope._props.hasOwnProperty(key) || 
                    prototype._$scope._state.hasOwnProperty(key)) {
              debuger.warn(`Can not declare prop: ${key} for this Viewer,Viewer already has this prop`)
          }
          else {
              _methods[key] = methods[key]
          }
      }

      /****事件****/
      let _events = {}
      // 继承
      let events = parentProto._$scope._events
      for (let key in events) {
          _events[key] = events[key]
      }
      // 自定义
      events = property.events
      for (let key in events) {
          _events[key] = events[key]
      }

      // 原型域
      prototype._$scope = {_template, _templateUrl, _props, _state, _methods, _events}

      // 加入视图组
      Viewer._declares.push(DeclareViewer)

      // 返回新组件
      return DeclareViewer
  }

  /**
   * @description 对象方法继承
   * @param scope <Function/Object> 视图构造函数或对象
  */
  _$extend (scope) {
      // 生成属性集合
      let property = Viewer.packProto(scope)
      // 根原型
      let rootProto = Viewer.prototype

      // 视图域
      let $scope = this.$scope

      /****DOM****/
      $scope._el = property.el

      /****模板****/
      $scope._template = property.template || $scope._template
      $scope._templateUrl = property.templateUrl || $scope._templateUrl

      /****属性****/
      let _props = $scope._props
      let props = property.props
      for (let key in props) {
          // 根含有相同键
          if (rootProto.hasOwnProperty(key)) {
              debuger.warn(`Can not declare prop: ${key} for this Viewer,RootViewer already has this prop`)
          }
          // 子级有相同键
          else if ($scope._state.hasOwnProperty(key) || $scope._methods.hasOwnProperty(key)) {
              debuger.warn(`Can not declare prop: ${key} for this Viewer,Viewer already has this prop`)
          }
          else {
              _props[key] = props[key]
          }
      }

      /****状态****/
      let _state = $scope._state
      let state = property.state
      for (let key in state) {
          // 根含有相应属性
          if (rootProto.hasOwnProperty(key)) {
              debuger.warn(`Can not declare prop: ${key} for this Viewer,RootViewer already has this prop`)
          }
          // 子级有相同键
          else if ($scope._props.hasOwnProperty(key) || $scope._methods.hasOwnProperty(key)) {
              debuger.warn(`Can not declare prop: ${key} for this Viewer,Viewer already has this prop`)
          }
          else {
              _state[key] = state[key]
          }
      }

      /****方法****/
      let _methods = $scope._methods
      let methods = property.methods
      for (let key in methods) {
          // 根含有相同键
          if (rootProto.hasOwnProperty(key)) {
              debuger.warn(`Can not declare prop: ${key} for this Viewer,RootViewer already has this prop`)
          }
          // 属性有相同键
          else if ($scope._props.hasOwnProperty(key) || $scope._state.hasOwnProperty(key)) {
              debuger.warn(`Can not declare prop: ${key} for this Viewer,Viewer already has this prop`)
          }
          else {
              _methods[key] = methods[key]
          }
      }

      /****事件****/
      let _events = $scope._events
      let events = property.events
      for (let key in events) {
          _events[key] = events[key]
      }
  }

  /**
   * @description 编译模板
   * @param template <String> 模板字符
   * @param viewer <Viewer> 视图类
   * @return <Object>
  */
  static $compile (template, viewer) {
      // 视图处理
      viewer = viewer instanceof Viewer ? viewer : Viewer
      // 转化为视图节点
      let vnode = ViewerNode.parse(template, viewer)
      // 编译视图节点
      let render = vnode.compile()

      return {
          render: render,
          vnode: vnode
      }
  }

  /**
   * @description 编译模板
   * @param template <String> 模板字符
   * @return <Object>
  */
  $compile (template) {
      // 编译模板
      let compiler = Viewer.$compile(template, this)
      // 调用静态编译方法
      this._$vnode = compiler.vnode
      // 渲染函数
      this._$render = compiler.render

      return {
          render: compiler.render,
          vnode: compiler.vnode
      }
  }

  /**
   * @description 渲染元素
   * @return <HtmlElement>
  */
  $render () {
      // 无渲染函数生成
      if (!this._$render) {
          this.$compile(this.$scope._template)
      }
      // 生成视图元素
      this._$vel = this._$render(this)
      console.log(this._$vel)
      // 返回视图元素
      return this._$vel
  }

  /**
   * @description 重新渲染元素
   * @return <HtmlElement>
  */
  $reRender () {
      // 无元素先生成
      if (!this._$vel) {
          return this.$render()
      }

      // 生成视图元素
      let $vel = this._$render(this)
      // 重新渲染
      this._$vel.reRender($vel)

      // 生成视图元素
      return this._$vel
  }

  /**
   * @description 挂载元素
   * @param el <String/HTMLElement> // 元素选择器或dom元素
   * @param scope <Object/Function> // 配置对象或构造函数
   * @return <Viewer>
  */
  static $mount (el, scope) {
      scope = Viewer.packScope(scope)
      scope.el = el || scope.el
      // 生成视图对象
      let viewer = new Viewer(scope)
      return viewer
  }

  /**
   * @description 挂载元素
   * @param monutEl {HTMLElement} // 需要挂载的元素
  */
  $mount (monutEl) {
      monutEl = monutEl || this.el
      // 渲染生成元素
      let viewEl = this.$render()
      // DOM元素
      let domEl = null

      // 虚拟元素渲染成DOM元素
      if (viewEl instanceof VirtualElement) {
          domEl = viewEl.render()
      }

      // 判断元素并插入元素
      if (domEl instanceof HTMLElement) {
          // 插入元素
          monutEl.insertAdjacentElement('afterend', domEl)
          // 删除原元素
          // monutEl.remove()
      }
  }

  /**
   * @description 同步模型
   * @param key {String} // 键名
   * @param value {any} // 值
  */
  $sync (key, value) {
      console.log(key, value)
      if (this.hasOwnProperty(key)) {
          this[key] = value
      }

      // 重新渲染
      this.$reRender()
  }

  /**
   * @description 销毁视图
  */
  destroy () {

  }

  /**
   * @description 监控模型属性
   * @param key <String> 模型键名
   * @param fn <function> 监控函数
  */
  $watch (key, fn) {

  }

  /**
   * @description 监控模型属性
   * @param key <Object/String> 模型键名
   * @param model {Object} 模型对象
   * @param fn <function> 监控函数
  */
  _w (key, model, fn) {
      
  }

  /**
   * @description 属性
  */
  $props () {

  }

  /**
   * @description 数据
  */
  $data () {

  }

  /**
   * @function 更新视图
  */
  $update () {

  }

  /**
   * @function 视图向下传播事件
  */
  $broadcast () {

  }

  /**
   * @function 视图向好传播事件
  */
  $emit () {

  }

  /**
   * @description 添加依赖
   * @param params <Array/Object> // 依赖数组或空间、组件、指令
  */
  depends (params) {

  }

  /**
   * @description 取出视图
   * @param name <String> // 视图名称
   * @return <Viewer/null>
  */
  static $pullViewer (name) {
      if (name === 'container') {
          return {
              defaultProps () {
                  return []
              }
          }
      }

      return null
  }

  /**
   * @description 取出视图
   * @param name <String> // 视图名称
   * @return <Viewer/null>
  */
  $pullViewer (name) {
      if (name === 'container') {
          return {
              defaultProps () {
                  return []
              }
          }
      }

      return null
  }

  /**
   * @description 定义或获取指令，指令为单例
   * @param name <String> 指令名称
   * [@param scope <Function/Object> 指令构造函数或对象]
   * [@param viewer <Viewer> 视图对象]
   * @return <Object>
  */
  static directive (name, scope, viewer) {
      // 数组形式
      if (objecter.isArray(name)) {
          name.forEach(item => {
              Viewer.directive(item.name, item.scope, viewer)
          })
          return
      }

      // 参数不正确
      if (!name || (!objecter.isFunction(scope) && !objecter.isPlainObject(scope))) {
          debuger.warn(`Directive ${name} require right arguments`)
          return
      }

      // 生成控制对象
      scope = Viewer.packScope(scope)
      let dir = null
      // 指定视图
      viewer = viewer instanceof Viewer ? viewer : Viewer
      // 查找是否已经有相同名称的指令
      viewer._directives.map(item => {
          if (item.name === name) {
              dir = item
              return scope
          }
          return item
      })

      // 指令不存在添加至指令组
      if (!dir) {
          viewer._directives.push({
              name: name,
              scope: scope
          })
      }

      // 返回新指令
      return scope
  }

  /**
   * @description 指令
   * @param name <String> 指令名称
   * [@param scope <Function/Object> 指令构造函数或对象]
   * @return <Object>
  */
  $directive (name, scope) {
      return Viewer.directive(name, scope, this)
  }

  /**
   * @description 取出指令
   * @param name <String> // 指令名称
   * [@param viewer <Viewer> 视图对象]
   * @return <Object>
  */
  static $pullDirective (name, viewer) {
      let dir = null
      // 指定视图
      viewer = viewer instanceof Viewer ? viewer : Viewer
      // 本地查找
      viewer._directives.forEach(item => {
          if (item.name === name) {
              dir = item.scope
              return false
          }
      })

      return dir
  }

  /**
   * @description 取出指令
   * @param name <String> // 指令名称
   * @return <Object>
  */
  $pullDirective (name) {
      return Viewer.$pullDirective(name, this) || Viewer.$pullDirective(name)
  }

  /**
   * @description 设置状态
   * @param key <String/Object> 模型键名，以逗号间隔代表不同层级；是对象时直接覆盖
   * [@param data <any> 数据值]
   * */
  setState () {

  }

  /**
   * @description 设置属性
   * @param key <String/Object> 模型键名，以逗号间隔代表不同层级；是对象时直接覆盖
   * [@param data <any> 数据值]
  */
  setProps (key, data) {

  }

  // 事件对象
  // events = {
  //     beforeCreate () {},
  //     created () {},
  //     beforeMount () {},
  //     mounted () {},
  //     beforeUpdate () {},
  //     updated () {},
  //     activated () {},
  //     deactivated () {},
  //     beforeDestroy () {},
  //     destroyed () {},
  //     errorCaptured () {}
  // }

  /**
   * @description 管道
   * @param name <String> 管道名称
   * @param fn <Function> 管道编译函数
  */
  static pipe (name, fn) {

  }

  /**
   * @description 管道
   * @param name <String> 管道名称
   * @param fn <function> 管道编译函数
  */
  pipe (name, fn) {

  }

  /**
   * @description 包装控制域对象
   * @param scope <Function/Object> 控制域构造函数或对象
   * @return <Object>
  */
  static packScope (scope) {
      // 构造函数
      if (objecter.isFunction(scope)) {
          function F() {
              let result = scope.call(this)
              if (objecter.isPlainObject(result)) {
                  for (let key in result) {
                      this[key] = result[key]
                  }
              }
          }

          // 生成控制域对象
          scope = new F()
      }
      // 非对象
      else if (!scope) {
          scope = {}
      }

      return scope
  }

  /**
   * @description 包装组件属性
   * @param scope <Function/Object> 控制域构造函数或对象
   * {
   *  template: <String/Function> // 模板字符串或生成函数
   *  templateUrl: <String/Function> // 模板地址或生成函数
   *  props () {} // 属性，可以直接返回值，或者使用方法返回
   *  可提供的形式为：
   *  1、字符 props: 'name'
   *  2、数组 props: ['name', 'width', 'height']
   *  3、对象 props: 
   *  {
   *      name: 'Component',
   *      width: {
   *          default: 0, // 默认值
   *          type: Number, // 类型
   *          required: true, // 是否必须
   *          validator: function (value) { // 验证方法或正则表达式，不通过不赋值，优先级低于类型
   *              return value >= 0
   *          }
   *      }
   *  }
   *  state () {} // 状态对象，可以直接返回值，或者使用方法返回
   *  例1,直接赋值对象:
   *  state: {
   *      name: 'Dog'
   *  }
   *  例2,通过函数计算返回:
   *  state () {
   *      return {name: 'Dog'}
   *  }
   *  methods () {} 方法对象，可以直接返回值，或者使用方法返回
   *  例1,直接赋值对象：
   *  methods: {
   *      getName () {return this.name}
   *  }
   *  例2,通过函数计算返回：
   *  methods () {
   *      return {
   *          getName () {return this.name}
   *      }
   *  }
   *  events () {} // 事件对象，可以直接返回值，或者使用方法返回
   *  例1,直接赋值对象:
   *  events: {
   *      show () {}
   *  }
   *  例2,通过函数计算返回:
   *  events () {
   *      return {show () {}}
   *  }
   * }
   * @return <Object>
  */
  static packProto (scope) {
      // 生成控制对象
      scope = Viewer.packScope(scope)

      /****处理模板****/
      let template = (objecter.isFunction(scope.template) || 
                      objecter.isString(scope.template)) ? 
                      scope.template : ''
      let templateUrl = (objecter.isFunction(scope.templateUrl) || 
                          objecter.isString(scope.templateUrl)) ? 
                          scope.templateUrl : ''

      /****处理props****/
      let props = scope.props
      let declareProps = {}
      // 如果是函数，先执行取出结果
      props = objecter.isFunction(props) ? scope.props() : props

      // 字符形式
      if (objecter.isString(props)) {
          declareProps[props] = {
              default: undefined
          }
      }
      // 数组形式
      else if (objecter.isArray(props)) {
          props.forEach(item => {
              objecter.isString(item) && (declareProps[item] = {
                  default: undefined
              })
          })
      }
      // 对象形式
      else if (objecter.isPlainObject(props)) {
          // 属性默认键
          let keys = ['default', 'type', 'required', 'validator']
          for (let item in props) {
              let prop = props[item]
              // 值为对象时
              if (objecter.isPlainObject(prop)) {
                  for (let key in prop) {
                      if (keys.indexOf(key) > -1) {
                          if (key === 'required') {
                              declareProps[key] = !!prop[key]
                          }
                          else if (key === 'validator') {
                              // 验证器支持函数与正则
                              declareProps[key] = objecter.isRegexp(prop[key]) || 
                                  objecter.isFunction(prop[key]) ? 
                                  prop[key] : undefined
                          }
                          else {
                              declareProps[key] = prop[key]
                          }
                      }
                  }
              }
              // 其它形式
              else {
                  declareProps[item] = prop
              }
          }
      }

      /****处理data****/
      let state = scope.state
      let declareState = {}
      // 如果是函数，先执行取出结果
      state = objecter.isFunction(state) ? scope.state() : state

      // 对象形式
      if (objecter.isPlainObject(state)) {
          for (let key in state) {
              declareState[key] = state[key]
          }
      }

      /****处理methods****/
      let methods = scope.methods
      let declareMethods = {}
      // 如果是函数，先执行取出结果
      methods = objecter.isFunction(methods) ? scope.methods() : methods

      // 对象形式
      if (objecter.isPlainObject(methods)) {
          for (let key in methods) {
              objecter.isFunction(methods[key]) && (declareMethods[key] = methods[key])
          }
      }

      /****处理events****/
      let events = scope.events
      let declareEvents = {}
      // 如果是函数，先执行取出结果
      events = objecter.isFunction(events) ? scope.events() : events

      // 对象形式
      if (objecter.isPlainObject(events)) {
          for (let key in events) {
              objecter.isFunction(events[key]) && (declareEvents[key] = events[key])
          }
      }

      scope.template = template
      scope.templateUrl = templateUrl
      scope.props = declareProps
      scope.state = declareState
      scope.methods = methods
      scope.events = declareEvents

      return scope
  }

  /**
   * @description 函数体生成
   * @param callback <Function> // 函数
   * @return <Element>
  */
  _f (callback) {
      return callback()
  }

  /**
   * @description 标签元素生成
   * @param tagName <String> // 标签名
   * @param configure <Object> // 属性相关
   * @return <Element>
  */
  _e (tagName, configure) {
      // 虚拟元素
      // let el = doc.createElement(tagName)
      // 虚拟元素
      let el = VirtualElement.createElement(tagName, this)

      // 属性设置
      let attributes = configure.attributes
      for (let key in attributes) {
          el.setAttribute(key, attributes[key])
      }

      // 指令处理
      let directives = configure.directives || []
      directives.forEach(item => {
          // 取出指令
          let direct = this.$pullDirective(item.name)
          // 编译指令
          direct.compile(el, item, this)
      })

      // 子元素
      let childNodes = configure.childNodes
      // 添加子元素
      append(el, childNodes)

      /**
       * @description 添加元素
       * @param parentNode <HtmlElement> // 父元素
       * @param nodes <Array> // 元素数组
      */
      function append (parentNode, nodes) {
          // 判定是否是数组
          if (!objecter.isArray(nodes)) {
              return parentNode
          }
          // 遍历元素数组
          nodes.forEach(item => {
              // 元素数组
              if (objecter.isArray(item)) {
                  append(parentNode, item)
              }
              // 含有元素内容则添加
              else if (item) {
                  // 添加子节点
                  parentNode.appendChild(item)
                  // 设置父节点
                  item.parentNode = parentNode
              }
          })
      }

      // 保存元素
      this._vel = el

      return el
  }

  /**
   * @description 文本元素生成
   * @param text <String> // 文本
   * [@param textSecond <String> // 文本]
   * [@param textThird <String> // 文本]
   * @return <Element>
  */
  _t (text) {
      // 取出字符串
      let args = Array.from(arguments)
      // 合并字符
      //return doc.createTextNode(args.join(''))
      // 虚拟元素
      return VirtualElement.createTextNode(args.join(''), this)
  }

  /**
   * @description 表达式编译
   * @param express <String> // 表达式
   * @return <Text>
  */
  _c (express) {
      return express
  }

  /**
   * @description 指令编译
   * @param name <String> // 指令名称
   * @return <String>
  */
  _d (name) {
      // 查找指令
      let direct = this.$pullDirective(name)
      // 取参
      let args = [].slice.call(arguments, 1)

      // 执行编译函数
      return direct.compile.apply(this, args)
  }

  /**
   * @description 分析模板变量
   * @param code <String> // 模板字符
   * @return <Array>
  */
  static forkVariable (code) {
      var KEYWORDS =
          // 关键字
          'break,case,catch,continue,debugger,default,delete,do,else,false'
          + ',finally,for,function,if,in,instanceof,new,null,return,switch,this'
          + ',throw,true,try,typeof,var,void,while,with'
          // 保留字
          + ',abstract,boolean,byte,char,class,const,double,enum,export,extends'
          + ',final,float,goto,implements,import,int,interface,long,native'
          + ',package,private,protected,public,short,static,super,synchronized'
          + ',throws,transient,volatile'
          // ECMA 5 - use strict
          + ',arguments,let,yield'
          + ',undefined'
      var REMOVE_RE = /\/\*[\w\W]*?\*\/|\/\/[^\n]*\n|\/\/[^\n]*$|"(?:[^"\\]|\\[\w\W])*"|'(?:[^'\\]|\\[\w\W])*'|\s*\.\s*[$\w\.]+/g
      var SPLIT_RE = /[^\w$]+/g
      var KEYWORDS_RE = new RegExp(["\\b" + KEYWORDS.replace(/,/g, '\\b|\\b') + "\\b"].join('|'), 'g')
      var NUMBER_RE = /^\d[^,]*|,\d[^,]*/g
      var BOUNDARY_RE = /^,+|,+$/g
      var SPLIT2_RE = /^$|,+/

      return code
          .replace(REMOVE_RE, '')
          .replace(SPLIT_RE, ',')
          .replace(KEYWORDS_RE, '')
          .replace(NUMBER_RE, '')
          .replace(BOUNDARY_RE, '')
          .split(SPLIT2_RE)
  }
}

/****视图原型属性****/
Viewer.prototype._$scope = {
    _template: null,
    _templateUrl: null,
    _props: {},
    _state: {},
    _methods: {},
    _events: {}
}

// 定义的视图集合
Viewer._declares = []
// 定义的指令集合
Viewer._directives = []

// 添加自定义指令
Viewer.directive(directives)

export default Viewer